/* Copyright 2009 Palm, Inc.  All rights reserved. */

/**
 * Most of the content for this file comes from the
 * file formatting-utils.js. The function periodFormatter 
 * is from the file formatter_service.js. Both the files are 
 * part of the Calendar application and is Copyright Palm, Inc.
 * Please refer to the Palm SDK License agreement for their terms.
 * 
 * The function isSameDate Copyright (C) 2010 Krishna Sundaresan
 * and is released under the GNU Lesser General Public License Version 3
 * (or if you prefer) higher.
 */
//Number of days in each month of a leap year
var leapYearDaysInMonth = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

//Number of days since January 1 at the end of each month of a leap year
var leapYearDaysCumulative = [31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366];

//Number of days in each month of a regular year
var regularYearDaysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];

//Number of days since January 1 at the end of each month of a regular year
var regularYearDaysCumulative = [31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];

//Number of days until December 31 at the start of each month of a leap year
var leapYearDaysCumulativeReverse = [366, 335, 306, 275, 245, 214, 184, 153, 122, 92, 61, 31];

//Number of days until December 31 at the start of each month of a regular year
var regularYearDaysCumulativeReverse = [365, 334, 306, 275, 245, 214, 184, 153, 122, 92, 61, 31];

//Returns true if the year is a leap year
function isLeapYear(year){
    if (year % 4) 
        return false;
    if (year % 400 == 0) 
        return true;
    if (year % 100 == 0) 
        return false;
    return true;
}

//finds # of days between January 1 and the given date, in the year of the given date.
//Timezone agnostic
function howManyDaysSinceJanuaryFirst(date){
    var howManyDays = 0;
    var day = date.getDate();
    var year = date.getFullYear();
    var previousMonth = date.getMonth() - 1;
    
    //add the days for all previous months
    if (previousMonth >= 0) {
        if (isLeapYear(year)) 
            howManyDays = leapYearDaysCumulative[previousMonth];
        else 
            howManyDays = regularYearDaysCumulative[previousMonth];
    }
    
    //add the days for the current month
    howManyDays += (day - 1);
    
    return howManyDays;
}

//finds # of days between the given date and December 31, in the year of the given date.
//Timezone agnostic
function howManyDaysTillDecember31(date){
    var howManyDays = 0;
    var day = date.getDate();
    var year = date.getFullYear();
    var month = date.getMonth();
    var nextMonth = date.getMonth() + 1;
    var daysInMonthArray = regularYearDaysInMonth;
    
    //add the days for all months after the current month
    if (nextMonth < 12) {
        if (isLeapYear(year)) {
            daysInMonthArray = leapYearDaysInMonth;
            howManyDays = leapYearDaysCumulativeReverse[nextMonth];
        }
        else {
            howManyDays = regularYearDaysCumulativeReverse[nextMonth];
        }
    }
    
    //add the days left in the current month
    howManyDays += (daysInMonthArray[month] - day);
    
    return howManyDays;
}

//finds # of days between two given dates.
//Require: dates are within the same year
//Require: startRange < endRange
//Timezone agnostic     
function howManyDaysBetweenShortRange(startDate, endDate){
    var howManyDays = 0;
    var daysInMonthArray = regularYearDaysInMonth;
    var cumulativeArray = regularYearDaysCumulative;
    var startMonth = startDate.getMonth();
    var startDay = startDate.getDate();
    var year = startDate.getFullYear();
    
    var endMonth = endDate.getMonth();
    var endDay = endDate.getDate();
    var monthDiff = endMonth - startMonth;
    
    //if we are within the same month
    if (monthDiff == 0) {
        return (endDay - startDay);
    }
    else {
        if (isLeapYear(year)) {
            daysInMonthArray = leapYearDaysInMonth;
            cumulativeArray = leapYearDaysCumulative;
        }
        
        //add days left in the start month
        howManyDays += (daysInMonthArray[startMonth] - startDay);
        
        //add days past in the end month
        howManyDays += endDay;
        
        //add days in months in between
        if (monthDiff > 1) 
            howManyDays += (cumulativeArray[endMonth - 1] - cumulativeArray[startMonth]);
    }
    
    return howManyDays;
}

//finds # of days between two given dates.
//Require: startRange < endRange
//Timezone agnostic
function howManyDaysBetween(startDate, endDate){
    var howManyDays = 0;
    
    var startYear = startDate.getFullYear();
    var endYear = endDate.getFullYear();
    if (startYear == endYear) {
        howManyDays = howManyDaysBetweenShortRange(startDate, endDate);
    }
    else {
        howManyDays += howManyDaysTillDecember31(startDate);
        howManyDays += howManyDaysSinceJanuaryFirst(endDate) + 1;
        
        for (var year = startYear + 1; year < endYear; year++) {
            if (isLeapYear(year)) 
                howManyDays += 366;
            else 
                howManyDays += 365;
        }
    }
    return howManyDays;
}

//finds # of whole months between two given dates.
//Require: startDate < endDate
//Timezone agnostic
function howManyMonthsBetween(startDate, endDate){
    var howManyMonths = 0;
    
    var startMonth = startDate.getMonth();
    var startYear = startDate.getFullYear();
    
    var endMonth = endDate.getMonth();
    var endYear = endDate.getFullYear();
    
    if (startYear == endYear) {
        return endMonth - startMonth;
    }
    else {
        howManyMonths += (12 - startMonth);
        howManyMonths += endMonth;
        howManyMonths += (endYear - startYear - 1) * 12;
    }
    return howManyMonths;
}

//Dissects the period specified by startDate and endDate into the 
//number of years, months, days, hours, and minutes between the two.
//Returns an object formatted: {years, months, days, hours, minutes}.
function getTimePeriodParts(startDate, endDate, ignoreTime){

    var period = {
        years: 0,
        months: 0,
        days: 0,
        hours: 0,
        minutes: 0
    };
    
    var monthsBetween = howManyMonthsBetween(startDate, endDate);
    if (startDate.getDate() > endDate.getDate()) 
        monthsBetween--;
    period.years = Math.floor(monthsBetween / 12);
    period.months = monthsBetween % 12;
    
    if (endDate.getDate() >= startDate.getDate()) 
        period.days = endDate.getDate() - startDate.getDate();
    else {
        var jumpDate = startDate.getDate();
        var jumpMonth = endDate.getMonth() - 1;
        var jumpYear = endDate.getFullYear();
        if (jumpMonth < 0) {
            jumpMonth = 11;
            jumpYear--;
        }
        var tempDate = new Date(jumpYear, jumpMonth, jumpDate);
        period.days = howManyDaysBetween(tempDate, endDate);
    }
    
    if (endDate.getHours() >= startDate.getHours()) 
        period.hours = endDate.getHours() - startDate.getHours();
    else {
        period.hours = endDate.getHours() + 24 - startDate.getHours();
        period.days--;
    }
    
    if (endDate.getMinutes() >= startDate.getMinutes()) 
        period.minutes = endDate.getMinutes() - startDate.getMinutes();
    else {
        period.minutes = endDate.getMinutes() + 60 - startDate.getMinutes();
        period.hours--;
    }
    
    if (ignoreTime) {
        period.hours = 0;
        period.minutes = 0;
    }
    
    return period;
}

function periodFormatter(period){

    Mojo.Log.info("***********period:" + Object.toJSON(period));
    var params = [];
    var result;
    tempModel = {};
    
    if (period.years > 0) {
        var temp = $L("1# #{year} year|# #{year} years");
        tempModel.year = period.years;
        params.push(Mojo.Format.formatChoice(period.years, temp, tempModel));
        
    }
    if (period.months > 0) {
        var temp = $L("1# #{month} month|# #{month} months");
        tempModel.month = period.months;
        params.push(Mojo.Format.formatChoice(period.months, temp, tempModel));
        
    }
    if (period.weeks > 0) {
    
        var temp = $L("1# #{week} week|# #{week} weeks");
        tempModel.week = period.weeks;
        params.push(Mojo.Format.formatChoice(period.weeks, temp, tempModel));
    }
    if (period.days > 0) {
    
        var temp = $L("1# #{day} day|# #{day} days");
        tempModel.day = period.days;
        params.push(Mojo.Format.formatChoice(period.days, temp, tempModel));
    }
    
    if (period.hours > 0) {
        var temp = $L("1# #{hour} hour|# #{hour} hours");
        tempModel.hour = period.hours;
        params.push(Mojo.Format.formatChoice(period.hours, temp, tempModel));
        
    }
    if (period.minutes > 0) {
        var temp = $L("1# #{minute} minute|# #{minute} minutes");
        tempModel.minute = period.minutes;
        params.push(Mojo.Format.formatChoice(period.minutes, temp, tempModel));
        
    }
    Mojo.Log.info("***********params content:" + Object.toJSON(params));
    
    if (params.length == 1) {
        result = params[0];
    }
    else 
        if (params.length == 2) {
            result = params[0] + $L(" and ") + params[1];
        }
        else {
            var resultStr = "";
            for (i = 0; i < params.length - 1; i++) {
                resultStr = resultStr + params[i] + $L(", ");
            }
            result = resultStr + $L(" and ") + params[params.length - 1];
            
        }
    Mojo.Log.info("************result string is:" + result)
    return result;
}

function isSameDate(date1, date2){

    return date1.getDate() == date2.getDate() && 
	date1.getMonth() == date2.getMonth() && 
	date1.getFullYear() == date2.getFullYear()
    
}
